package cn.xeblog.plugin.action;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.DialogWrapper;
import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 防沉迷行为：默认开启。
 * <p>
 * 该命令用于防止程序猿因过度使用 IDEA，而产生的疲劳、困倦，进而导致猝死等一系列危及生命安全问题的出现。
 *
 * @author anlingyi
 * @date 2021/9/4 12:39 下午
 */
public class AliveAction {

  /**
   * 是否正在运行
   */
  private static boolean running;

  /**
   * 是否开启该功能
   */
  private static boolean enabled;

  /**
   * 工作时间，单位：秒
   */
  private static long workTime = TimeUnit.HOURS.toSeconds(1);

  /**
   * 休息时间，单位：秒
   */
  private static long restTime = TimeUnit.MINUTES.toSeconds(10);

  /**
   * 下一次提醒的时间（精确到秒的时间戳）
   */
  private static long nextStartTime;

  /**
   * 关闭窗口锁定的密码
   */
  private static final String GAN = "我只想搞钱";

  /**
   * 设置工作时间
   * @param second 秒
   */
  public static void setWorkTime(int second) {
    if (second < 0) {
      return;
    }

    workTime = second;
  }
  /**
   * 设置休息时间
   * @param second 秒
   */
  public static void setRestTime(int second) {
    if (second < 0) {
      return;
    }

    restTime = second;
  }

  /**
   * 设置是否开启该功能
   *
   * @param bool true,开启该功能
   */
  public static void setEnabled(boolean bool) {
    // 开启
    if (bool) {
      // 未开启，设置下一次开始时间
      if (!enabled) {
        setNextStartTime();
        run();
      }
    } else {
      // 没开启设置为非运行中
      running = false;
    }

    // 设置功能开启标识
    enabled = bool;
  }

  /**
   * 获取现在时间秒数
   *
   * @return 现在时间秒数
   */
  private static long getNowTimeSecond() {
    return System.currentTimeMillis() / 1000;
  }

  /**
   * 刷新下一次开始时间
   *
   * @return true，设置成功，否则，false
   */
  public static boolean flushNextStartTime() {
    // 当前时间大于下一次的开始时间，即超出了下一次开始时间时，重新设置下一次开始时间
    if (getNowTimeSecond() > nextStartTime) {
      setNextStartTime();
      return true;
    }

    return false;
  }

  /**
   * 设置下一次开始时间
   */
  private static void setNextStartTime() {
    nextStartTime = getNowTimeSecond() + workTime;
  }

  /**
   * 获取下一次提醒的时间
   *
   * @return 下一次提醒的时间
   */
  public static long getNextStartTime() {
    return nextStartTime;
  }

  /**
   * 是否开启该功能
   *
   * @return true启动，否则，false
   */
  public static boolean isEnabled() {
    return enabled;
  }

  /**
   * 是否继续执行
   *
   * @return true启动，否则，false
   */
  public static boolean isContinued() {
    //开户并且正在运行中
    return enabled && running;
  }

  private static void run() {
    // 主进程
    Timer timer = new Timer(true);
    timer.schedule(new TimerTask() {
      @Override
      public void run() {
        // 没开启，就取消
        if (!enabled) {
          timer.cancel();
          return;
        }

        // 当现在时间等于下次开始时间时，
        if (getNowTimeSecond() == nextStartTime) {
          ApplicationManager.getApplication().invokeLater(() -> areYouOk());
        }
      }
    }, 0, 1000);
  }

  private static void areYouOk() {
    // 如果正在运行中，跳过
    if (running) {
      return;
    }

    // 构建存活对象，然后展示
    AliveDialogWrapper alive = new AliveDialogWrapper(restTime);
    alive.show();
  }

  /**
   * 存活对话框包装器(即防沉迷面板,默认开启。该命令用于防止程序猿因过度使用 IDEA，而产生的疲劳、困倦，进而导致猝死等一系列危及生命安全问题的出现)
   */
  private static class AliveDialogWrapper extends DialogWrapper {

    /**
     * 输入框
     */
    JTextField input = new JTextField();

    /**
     * 按钮
     */
    JButton button = new JButton();

    /**
     * 倒计时显示
     */
    JLabel timeLabel = new JLabel("00:00:00");

    /**
     * 休息时间（秒）
     */
    long second;

    public AliveDialogWrapper(long second) {
      super(true);

      this.second = second;

      // 初始化对话框
      setTitle("Are You Ok ?");
      setResizable(true);
      setCrossClosesWindow(false);

      init();
    }

    @Override
    protected @Nullable JComponent createCenterPanel() {
      // 创建中心对话框面板
      int width = 200;
      int height = 130;
      int widthHalf = width / 2;
      // 主面板
      JPanel main = new JPanel();
      main.setLayout(null);
      main.setMinimumSize(new Dimension(width, height));

      // 提示语
      JLabel tipsLabel = new JLabel("休息一下，马上回来...");
      tipsLabel.setFont(new Font(null, 0, 14));
      int tipsWidth = getFontWidth(tipsLabel);
      tipsLabel.setBounds(widthHalf - tipsWidth / 2, 0, tipsWidth, 20);

      // 倒计时时间
      timeLabel.setFont(new Font(null, 1, 18));
      int timeWidth = getFontWidth(timeLabel);
      timeLabel.setBounds(widthHalf - timeWidth / 2, 20, timeWidth, 35);

      // 输入框
      input.setBounds(10, 60, 180, 30);

      // 按钮
      button.setBounds(60, 95, 80, 35);
      button.setText("肝！");
      button.setForeground(new Color(0xDB4141));

      // 按钮添加监听，只有当用户输入“我只想搞钱”才可以关闭
      button.addActionListener(e -> {
        if (GAN.equals(input.getText())) {
          stop(true);
        }
      });

      main.add(tipsLabel);
      main.add(timeLabel);
      main.add(input);
      main.add(button);

      return main;
    }

    /**
     * 计算字体宽度
     *
     * @param label label标签对象
     * @return 宽度
     */
    private int getFontWidth(JLabel label) {
      String text = label.getText();
      int width = label.getFontMetrics(label.getFont()).stringWidth(text);
      return width + width / text.length();
    }

    @Override
    protected @NotNull Action[] createActions() {
      return new Action[]{};
    }

    /**
     * 倒计时
     */
    private void countdown() {
      // 调度器
      Timer timer = new Timer();
      // 每秒执行
      timer.schedule(new TimerTask() {
        // 休息时间
        long time = second;

        @Override
        public void run() {
          // 结束休息或者暂停
          if (--time < 0 || !isContinued()) {
            // 任务取消并且停止
            timer.cancel();
            stop(false);

            input.setEnabled(false);
            button.setEnabled(true);
            button.setText("I'm Fine.");
            button.setForeground(new Color(0x21BD21));
            button.addActionListener(e -> stop(true));

            return;
          }

          // 渲染倒计时显示
          long hour = time / 60 / 60;
          long minute = (time / 60 - hour * 60) % 60;
          long second = time - hour * 60 * 60 - minute * 60;

          StringBuilder sb = new StringBuilder();
          if (hour < 10) {
            sb.append("0").append(hour);
          } else {
            sb.append(hour);
          }
          sb.append(":");
          if (minute < 10) {
            sb.append("0").append(minute);
          } else {
            sb.append(minute);
          }
          sb.append(":");
          if (second < 10) {
            sb.append("0").append(second);
          } else {
            sb.append(second);
          }

          timeLabel.setText(sb.toString());
        }
      }, 0, 1000);
    }

    /**
     * 停止任务
     *
     * @param exit 是否退出
     */
    private void stop(boolean exit) {
      // 设置为非运行
      running = false;

      // 设置下一次开始的时间
      if (exit) {
        setNextStartTime();
        // 非UI线程中进行操作,关闭窗口
        ApplicationManager.getApplication().invokeLater(() -> close(0));
      }
    }

    /**
     * 显示
     */
    public void show() {
      // 正在运行中，跳过
      if (running) {
        return;
      }

      // 设置状态
      running = true;
      countdown();
      // 显示
      super.show();
    }
  }

}
